package com.efrei.schoolmanager.views;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.IOException;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.hibernate.HibernateException;

import com.efrei.schoolmanager.controlers.ControleurEleves;
import com.efrei.schoolmanager.exceptions.LogicException;
import com.efrei.schoolmanager.exceptions.PDFException;
import com.efrei.schoolmanager.model.ModeleTableauNonEditable;
import com.efrei.schoolmanager.model.obj.Classe;
import com.efrei.schoolmanager.model.obj.Eleve;
import com.efrei.schoolmanager.model.obj.Responsable;
import com.efrei.schoolmanager.printing.GenerePdf;
import com.efrei.schoolmanager.printing.PrintPdf;
import com.efrei.schoolmanager.tools.Tools;
import com.efrei.schoolmanager.views.components.CustomButton;
import com.efrei.schoolmanager.views.components.CustomTextField;

public class VueBulletinAbsences extends JPanel {
	private static final long serialVersionUID = 4377720080830064411L;

	private final static String TITLE = "Saisie d'un bulletin d'absences";

	// Proprietaire de cette dialog(objectif: rendre modale la jdialog)
	private final JFrame proprio;

	// JPanels
	private JPanel titlePanel, centerPanel, nomPrenomPanel, nomPrenomWestPanel,
			responsablePanel, responsableWestPanel, sujetPanel, sujetWestPanel,
			messageLabelPanel, messagePanel, messageLabelWestPanel,
			buttonsPanel, buttonsCenterPanel, infosPanel, aRemplirPanel,
			absencesPanel, absencesButtonsPanel;

	// JButtons
	private CustomButton enregistrerButton, imprimerButton,
			ajouterAbsenceButton, retirerAbsenceButton;

	// JLabels
	private JLabel titleLabel, responsableLabel, nomLabel, prenomLabel,
			classeLabel, sujetLabel, messageLabel;

	// JTextField
	private CustomTextField nomEleveTextField, prenomEleveTextField,
			classeEleveTextField;

	// JTextfield non personnalisé
	private JTextField sujetTextField;

	// JTable
	private JTable absencesTable;

	// JCombobox
	private JComboBox responsableComboBox;

	// CustomTextArea
	private JTextArea messageArea;

	// DefaultTableModel : modele de table par defaut est suffisant pour les
	// donnees d'absences
	private ModeleTableauNonEditable modelTable;

	// Eleve selectionne précédemment dans la dialog
	protected Eleve eleveSelectionne;

	// Le controleur permettant d'avoir de lancer la fenetre de recherche
	// d'eleve et d'obtenir les informations sur l'eleve selectionne
	private ControleurEleves controleur;

	public VueBulletinAbsences(JFrame proprio) throws HibernateException,
			LogicException {
		super();
		this.proprio = proprio;
		selectionEleve();
		if (eleveSelectionne != null) {
			initLabel();
			initButtons();
			initTextArea();
			initTextField();
			initComboBox();
			initTable();
			remplirNomPrenomPanel();
			remplirTitlePanel();
			remplirSujetPanel();
			remplirMessageLabelPanel();
			remplirMessagePanel();
			remplirButtonsPanel();
			remplirResponsablesPanel();
			remplirInfosPanel();
			remplirAbsencesPanel();
			remplirAbsencesButtonsPanel();
			remplirARemplirPanel();
			remplirCenterPanel();
			configurerVue();
			remplirChampsGeneraux();
			remplirSujetMessage();
		}

	}

	/**
	 * Remplissage automatique d'un message generique dans le sujet et le
	 * message
	 */
	private void remplirSujetMessage() {

		sujetTextField.setText("Bulletin d'absences (Eleve "
				+ eleveSelectionne.getNom().toUpperCase() + " "
				+ eleveSelectionne.getPrenom() + ")");
		messageArea
				.setText("Madame,Monsieur, \n\nVeuillez trouver ci-joint le bulletin d'absences pour l'eleve suivant dont vous etes responsable : "
						+ eleveSelectionne.getNom().toUpperCase()
						+ " "
						+ eleveSelectionne.getPrenom() + " .");
	}

	/**
	 * Lancement de la dialog de recherche d'eleve : celle ci nous retourne un
	 * eleve (celui qui vient d'etre selectionne)
	 * 
	 * @throws HibernateException
	 * @throws LogicException
	 */
	private void selectionEleve() throws HibernateException, LogicException {
		// Initialisation de la transaction
		controleur = new ControleurEleves();
		// Recherche d'un eleve
		VueRechercherEleve dialog = new VueRechercherEleve(proprio, controleur);
		eleveSelectionne = dialog.showDialog();
	}

	/**
	 * Remplissage automatique des champs de nom,prenom,classe et responsable de
	 * l'eleve selectionne
	 */
	private void remplirChampsGeneraux() {
		// Recuperation du nom et prenom
		nomEleveTextField.setText(eleveSelectionne.getNom().toUpperCase());
		prenomEleveTextField.setText(eleveSelectionne.getPrenom());

		// Recuperation de la classe
		Classe classeActuelle = recupClasseActuelle();
		if (classeActuelle != null) {
			classeEleveTextField.setText(classeActuelle.getNom());
		} else {
			classeEleveTextField.setText("Aucune classe");
		}

		// Recuperation des reponsables
		Set<Responsable> Setresponsables = eleveSelectionne
				.getResponsablesLegaux();
		responsableComboBox.addItem("-- Choisir un responsable --");
		for (Responsable responsable : Setresponsables) {
			responsableComboBox.addItem(responsable);
		}

	}

	/**
	 * Choix de la classe de l'eleve suivant la logique de la promotion la plus
	 * recente
	 * 
	 * @return
	 */
	private Classe recupClasseActuelle() {
		Set<Classe> setClasses = eleveSelectionne.getClasses();
		Classe classeActuelle = null;
		for (Classe classe : setClasses) {
			if (classeActuelle == null) {
				classeActuelle = classe;
			}
			if (classe.getPromotion() > classeActuelle.getPromotion()) {
				classeActuelle = classe;
			}
		}
		if (classeActuelle != null) {
			classeEleveTextField.setText(classeActuelle.getNom());
		} else {
			classeEleveTextField.setText("No classe ?");
		}
		return classeActuelle;
	}

	private void remplirAbsencesButtonsPanel() {
		absencesButtonsPanel = new JPanel();
		BoxLayout bl = new BoxLayout(absencesButtonsPanel, BoxLayout.PAGE_AXIS);
		absencesButtonsPanel.setLayout(bl);
		absencesButtonsPanel.add(ajouterAbsenceButton);
		absencesButtonsPanel.add(retirerAbsenceButton);
	}

	private void initTable() {
		modelTable = new ModeleTableauNonEditable();
		modelTable.addColumn("Date debut absence");
		modelTable.addColumn("Date fin absence");
		modelTable.addColumn("Raison");
		absencesTable = new JTable(modelTable);
		absencesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		ListSelectionModel listSelectionModel = absencesTable
				.getSelectionModel();
		listSelectionModel
				.addListSelectionListener(new AbsencesElevesTableListSelectionListener());
	}

	private void remplirAbsencesPanel() {
		absencesPanel = new JPanel(new BorderLayout());
		JScrollPane jsp = new JScrollPane(absencesTable);
		jsp.setPreferredSize(new Dimension(400, 100));
		absencesPanel.add(jsp, BorderLayout.NORTH);
	}

	private void remplirARemplirPanel() {
		aRemplirPanel = new JPanel();
		BoxLayout bl = new BoxLayout(aRemplirPanel, BoxLayout.PAGE_AXIS);
		aRemplirPanel.setLayout(bl);
		aRemplirPanel.add(sujetPanel);
		aRemplirPanel.add(messageLabelWestPanel);
		aRemplirPanel.add(messagePanel);
		aRemplirPanel.setBorder(BorderFactory
				.createTitledBorder("A completer si besoin"));

	}

	private void remplirInfosPanel() {
		infosPanel = new JPanel();
		BoxLayout bl = new BoxLayout(infosPanel, BoxLayout.PAGE_AXIS);
		infosPanel.setLayout(bl);
		infosPanel.add(nomPrenomWestPanel);
		infosPanel.add(responsableWestPanel);
		infosPanel.setBorder(BorderFactory
				.createTitledBorder("Eleve et responsables"));

	}

	private void remplirResponsablesPanel() {
		responsablePanel = new JPanel();
		// Gestionnaire de positionnement
		GroupLayout layout = new GroupLayout(responsablePanel);
		responsablePanel.setLayout(layout);
		// Espacement des composants
		layout.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		layout.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
		// 1e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				responsableLabel));
		// 2e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				responsableComboBox));
		layout.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
		// 1e ligne
		vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE)
				.addComponent(responsableLabel)
				.addComponent(responsableComboBox));
		layout.setVerticalGroup(vGroup);
		responsableWestPanel = new JPanel(new BorderLayout());
		responsableWestPanel.add(responsablePanel, BorderLayout.WEST);
	}

	private void initComboBox() {
		responsableComboBox = new JComboBox();
	}

	private void remplirButtonsPanel() {
		buttonsPanel = new JPanel(new FlowLayout());
		buttonsPanel.add(enregistrerButton);
		buttonsPanel.add(imprimerButton);
		buttonsCenterPanel = new JPanel(new BorderLayout());
		buttonsCenterPanel.add(buttonsPanel, BorderLayout.CENTER);
	}

	private void remplirMessagePanel() {
		messageArea.setLineWrap(true);
		JScrollPane jsp = new JScrollPane(messageArea);
		messagePanel = new JPanel(new BorderLayout());
		messagePanel.add(jsp, BorderLayout.WEST);
	}

	private void remplirMessageLabelPanel() {
		messageLabelPanel = new JPanel();
		// Gestionnaire de positionnement
		GroupLayout layout = new GroupLayout(messageLabelPanel);
		messageLabelPanel.setLayout(layout);
		// Espacement des composants
		layout.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		layout.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
		// 1e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(messageLabel));
		layout.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
		// 1e ligne
		vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE)
				.addComponent(messageLabel));
		layout.setVerticalGroup(vGroup);
		messageLabelWestPanel = new JPanel(new BorderLayout());
		messageLabelWestPanel.add(messageLabelPanel, BorderLayout.WEST);

	}

	private void remplirCenterPanel() {
		centerPanel = new JPanel();
		// Gestionnaire de positionnement
		BoxLayout bl = new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS);
		centerPanel.setLayout(bl);
		// Zone vide
		centerPanel.add(Box.createRigidArea(new Dimension(10, 10)));
		centerPanel.add(infosPanel);
		centerPanel.add(Box.createRigidArea(new Dimension(10, 20)));
		JPanel jp = new JPanel(new BorderLayout());
		// Bordure du panel
		jp.setBorder(BorderFactory.createTitledBorder("Absences"));
		jp.add(absencesPanel, BorderLayout.WEST);
		jp.add(absencesButtonsPanel, BorderLayout.CENTER);
		centerPanel.add(jp);
		centerPanel.add(Box.createRigidArea(new Dimension(10, 20)));
		centerPanel.add(aRemplirPanel);
		centerPanel.add(Box.createRigidArea(new Dimension(10, 20)));
		centerPanel.add(buttonsCenterPanel);
		// Bordure du panel
		centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
	}

	private void remplirSujetPanel() {
		sujetPanel = new JPanel();
		// Gestionnaire de positionnement
		GroupLayout layout = new GroupLayout(sujetPanel);
		sujetPanel.setLayout(layout);
		// Espacement des composants
		layout.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		layout.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
		// 1e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(sujetLabel));
		// 2e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				sujetTextField));
		layout.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
		// 1e ligne
		vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE)
				.addComponent(sujetLabel).addComponent(sujetTextField));
		layout.setVerticalGroup(vGroup);
		sujetWestPanel = new JPanel(new BorderLayout());
		sujetWestPanel.add(sujetPanel, BorderLayout.WEST);

	}

	private void initTextField() {
		nomEleveTextField = new CustomTextField();
		nomEleveTextField.setEditable(false);
		prenomEleveTextField = new CustomTextField();
		prenomEleveTextField.setEditable(false);
		classeEleveTextField = new CustomTextField();
		classeEleveTextField.setEditable(false);
		sujetTextField = new JTextField();
		sujetTextField.setMinimumSize(new Dimension(488, 20));
	}

	private void remplirTitlePanel() {
		titlePanel = new JPanel();
		titlePanel.add(titleLabel);
	}

	/**
	 * Configurer les options de la vue
	 */
	private void configurerVue() {
		this.setLayout(new BorderLayout());
		this.add(titlePanel, BorderLayout.NORTH);
		this.add(centerPanel, BorderLayout.CENTER);
	}

	private void remplirNomPrenomPanel() {
		nomPrenomPanel = new JPanel();
		// Gestionnaire de positionnement
		GroupLayout layout = new GroupLayout(nomPrenomPanel);
		nomPrenomPanel.setLayout(layout);
		// Espacement des composants
		layout.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		layout.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
		// 1e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(nomLabel));
		// 2e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				nomEleveTextField));
		// 3e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(prenomLabel));
		// 4e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				prenomEleveTextField));
		// 5e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(classeLabel));
		// 6e colonne
		hGroup.addGroup(layout.createParallelGroup().addComponent(
				classeEleveTextField));
		layout.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
		// 1e ligne
		vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE)
				.addComponent(nomLabel).addComponent(nomEleveTextField)
				.addComponent(prenomLabel).addComponent(prenomEleveTextField)
				.addComponent(classeLabel).addComponent(classeEleveTextField));
		layout.setVerticalGroup(vGroup);
		nomPrenomWestPanel = new JPanel(new BorderLayout());
		nomPrenomWestPanel.add(nomPrenomPanel, BorderLayout.WEST);
	}

	private void initTextArea() {
		messageArea = new JTextArea(15, 60);
	}

	private void initButtons() {
		enregistrerButton = new CustomButton("Enregistrer le document");
		enregistrerButton
				.addActionListener(new EnregistrerBulletinAbsencesListener());
		imprimerButton = new CustomButton("Imprimer le document");
		imprimerButton
				.addActionListener(new ImprimerBulletinAbsencesListener());
		ajouterAbsenceButton = new CustomButton("Ajouter une absence");
		ajouterAbsenceButton.addActionListener(new AjouterAbsenceListener());
		retirerAbsenceButton = new CustomButton("Retirer l'absence");
		retirerAbsenceButton.setEnabled(false);
		retirerAbsenceButton
				.addActionListener(new RetirerAbsenceActionListener());
	}

	private void initLabel() {
		titleLabel = new JLabel(TITLE);
		titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
		nomLabel = new JLabel("Nom: ");
		prenomLabel = new JLabel("Prenom:");
		classeLabel = new JLabel("Classe:");
		sujetLabel = new JLabel("Sujet: ");
		messageLabel = new JLabel("Message: ");
		responsableLabel = new JLabel("Envoyer au responsable: ");
	}

	private boolean verifAbsenceMini() {
		if (modelTable.getRowCount() > 0)
			return false;
		else
			JOptionPane.showMessageDialog(proprio,
					"Veuillez entrer au moins une absence", "Erreur",
					JOptionPane.ERROR_MESSAGE);
		return true;
	}

	/**
	 * @return le responsable selectionne ou null
	 */
	public Responsable getSelectedResponsable() {
		if (responsableComboBox.getSelectedIndex() == 0)
			return null;
		return (Responsable) responsableComboBox.getSelectedItem();
	}

	/**
	 * Listener pour l'appui sur le bouton d'ajout d'absence
	 * 
	 */
	class AjouterAbsenceListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			DialogAjouterAbsence dabs = new DialogAjouterAbsence(proprio);
			String absences[] = dabs.showDialog();
			if (absences != null && absences.length == 3) {
				modelTable.addRow(absences);
			}
		}
	}

	/**
	 * Listener pour la selection d'une ligne dans la table des absences
	 * (activation ou desactivation du bouton de retrait d'une absence)
	 * 
	 */
	class AbsencesElevesTableListSelectionListener implements
			ListSelectionListener {

		@Override
		public void valueChanged(ListSelectionEvent e) {
			if (absencesTable.getSelectedRow() != -1) {
				retirerAbsenceButton.setEnabled(true);
			} else {
				retirerAbsenceButton.setEnabled(false);
			}
		}

	}

	/**
	 * Listener pour la suppression d'une absence selectionne dans la table
	 * 
	 */
	class RetirerAbsenceActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {

			int selectedRow = absencesTable.getSelectedRow();
			modelTable.removeRow(selectedRow);
		}

	}

	/**
	 * Listener pour la generation du pdf et l'enregistrement sur le disque dur
	 * à l'aide du jfilechooser
	 * 
	 */
	class EnregistrerBulletinAbsencesListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			Responsable responsableChoisi = getSelectedResponsable();
			if (responsableChoisi == null) {
				if (responsableComboBox.getItemCount() == 1) {
					Tools.displayError(
							"Veuillez ajouter un responsable a cet eleve (Lister eleve puis modifier eleve).\n Ceci est necessaire pour la generation du document",
							"Pas de responsable");
				} else {
					Tools.displayError("Selectionner un responsable",
							"Responsable manquant");
				}
			} else {
				if (!verifAbsenceMini()) {
					JFileChooser jfc = new JFileChooser();
					jfc.showSaveDialog(proprio);
					if (jfc.getSelectedFile() != null) {
						try {
							GenerePdf.generePdfBulletinAbsences(
									sujetTextField.getText(),
									messageArea.getText(), responsableChoisi,
									eleveSelectionne, modelTable,
									jfc.getSelectedFile());
						} catch (PDFException ex) {
							System.err.println(ex);
							Tools.displayError(
									"Une erreur est survenue: "
											+ ex.getMessage(), "Erreur");
						}
					}
				}
			}
		}

	}

	/**
	 * Listener pour la generation du pdf et l'impression sur l'imprimante du
	 * choix de l'utilisateur
	 * 
	 */
	class ImprimerBulletinAbsencesListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			Responsable responsableChoisi = getSelectedResponsable();
			if (responsableChoisi == null) {
				if (responsableComboBox.getItemCount() == 1) {
					Tools.displayError(
							"Veuillez ajouter un responsable a cet eleve (Lister eleve puis modifier eleve).\n Ceci est necessaire pour la generation du document",
							"Pas de responsable");
				} else {
					Tools.displayError("Selectionner un responsable",
							"Responsable manquant");
				}
			} else {
				if (!verifAbsenceMini()) {
					{
						String projectDir = System.getProperty("user.dir");
						File tempFile = new File(projectDir + File.separator
								+ "temp.pdf");
						try {
							GenerePdf.generePdfBulletinAbsences(
									sujetTextField.getText(),
									messageArea.getText(), responsableChoisi,
									eleveSelectionne, modelTable, tempFile);
						} catch (PDFException ex) {
							System.err.println(ex);
							Tools.displayError(
									"Une erreur est survenue: "
											+ ex.getMessage(), "Erreur");
						}
						try {
							PrintPdf.printPdf(tempFile.getPath());
						} catch (IOException e1) {
							e1.printStackTrace();
						} catch (PrinterException e1) {
							e1.printStackTrace();
						} finally {
							tempFile.delete();
						}
					}
				}
			}
		}
	}
}
